﻿using LJ.Abstractions.Extensions;
using LJ.AspNetCore.Abstractions.Pack;
using LJ.WebApi.Abstractions;
using LJ.WebApi.Mvc.Filters;
using LJ.WebApi.Mvc.Internal;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace LJ.WebApi.Mvc.Extensions;

/// <summary>
/// 服务拓展
/// </summary>
public static class AspNetCorePackContextExtensions
{

    /// <summary>
    /// 添加DynamicWebApi
    /// </summary>
    /// <param name="packContext"></param>
    /// <returns></returns>
    public static IAspNetCorePackContext AddDynamicWebApi(this IAspNetCorePackContext aspNetCorePackContext)
    {
        aspNetCorePackContext.DependencyManager.ServiceCollection.AddTransient<IWebApiContext, WebApiContext>();

        aspNetCorePackContext.DependencyManager.ServiceCollection.AddTransient<IWebApiServiceConvention, WebApiServiceConvention>();
        // 添加控制器特性提供器
        var applicationPartManager = aspNetCorePackContext.DependencyManager.ServiceCollection.GetSingletonInstance<ApplicationPartManager>();
        var dynamicWebApiHandlerManager = aspNetCorePackContext.DependencyManager.ServiceCollection.GetSingletonInstance<IWebApiHandlerManager>();

        applicationPartManager.FeatureProviders.Add(new WebApiControllerFeatureProvider(dynamicWebApiHandlerManager));
        // 配置 Mvc 选项
        aspNetCorePackContext.DependencyManager.ServiceCollection.AddOptions<MvcOptions>()
           .Configure<IServiceProvider>((options, serviceProvider) =>
           {
               var webApiServiceConvention = serviceProvider.GetRequiredService<IWebApiServiceConvention>();

               // 添加应用模型转换器
               options.Conventions.Add(new WebApiApplicationModelConvention(webApiServiceConvention));

           });

        return aspNetCorePackContext;
    }

    /// <summary>
    /// 添加OpenApi
    /// </summary>
    /// <param name="packContext"></param>
    /// <returns></returns>
    public static IAspNetCorePackContext AddOpenApi(this IAspNetCorePackContext aspNetCorePackContext)
    {
        aspNetCorePackContext.DependencyManager.ServiceCollection.AddSwaggerGen();

        //packContext.OptionsManager.Add<PackSwaggerOptions>("Swagger");
        aspNetCorePackContext.DependencyManager.ServiceCollection.AddOptions<SwaggerGenOptions>()
            .Configure<IServiceProvider>((options, serviceProvider) =>
            {
                var webApiConfig = serviceProvider.GetConfig<WebApiConfig>();

                //每个 API 描述组创建一个 Swagger 文档
                // 为全部分组的控制器创建默认分组
                options.SwaggerDoc("ALL", new OpenApiInfo
                {
                    Title = "ALL",
                    Version = "ALL",
                });

                var apiDescriptionGroupCollectionProvider = serviceProvider.GetRequiredService<IApiDescriptionGroupCollectionProvider>();
                foreach (var description in apiDescriptionGroupCollectionProvider.ApiDescriptionGroups.Items)
                {
                    options.SwaggerDoc(description.GroupName, null);
                }

                //判断接口归于哪个分组
                options.DocInclusionPredicate((docName, apiDescription) =>
                {
                    if (docName == "ALL")
                    {
                        return true;
                    }
                    else
                    {
                        return apiDescription.GroupName == docName;
                    }
                });

                //添加注释文档
                var projectXmlComments = aspNetCorePackContext.ReflectionManager.GetAssemblies().Select(t => t.GetName()!.Name);
                foreach (var xmlComment in projectXmlComments)
                {
                    var assemblyXmlName = xmlComment!.EndsWith(".xml") ? xmlComment : $"{xmlComment}.xml";
                    var assemblyXmlPath = Path.Combine(AppContext.BaseDirectory, assemblyXmlName);

                    if (File.Exists(assemblyXmlPath))
                    {
                        options.IncludeXmlComments(assemblyXmlPath);
                        //var xmlDoc = new XPathDocument(assemblyXmlPath);
                        //SwaggerContext.XPathNavigators.Add(xmlDoc.CreateNavigator());
                    }
                    //options.RequestBodyFilter<WebApiRequestBodyFilter>();
                    //options.ParameterFilter<WebApiParameterFilter>();
                    //options.DocumentFilter<WebApiDocumentFilter>();
                    //options.OperationFilter<WebApiOperationFilter>();
                    //options.SchemaFilter<WebApiSchemaFilter>();


                    //options.OperationFilter<FileUploadOperationFilter>();
                }

                //添加认证
                foreach (var security in webApiConfig.Securitys)
                {
                    //添加Jwt验证设置,添加请求头信息
                    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                            {
                                new OpenApiSecurityScheme
                                {
                                    Reference = new OpenApiReference
                                    {
                                        Id = security.Id,
                                        Type = ReferenceType.SecurityScheme,
                                    }
                                },
                                new List<string>()
                            }
                    });

                    //放置接口Auth授权按钮
                    options.AddSecurityDefinition(security.Id, new OpenApiSecurityScheme
                    {
                        Description = security.Description,
                        Name = security.Name,//默认的参数名称
                        In = ParameterLocation.Header,//默认存放Authorization信息的位置(请求头中)
                        Type = SecuritySchemeType.ApiKey
                    });
                }
            });

        return aspNetCorePackContext;
    }

    /// <summary>
    /// 统一处理
    /// </summary>
    /// <param name="packContext"></param>
    /// <returns></returns>
    public static IAspNetCorePackContext AddUnifyData(this IAspNetCorePackContext aspNetCorePackContext)
    {
        //禁用模型验证过滤器
        aspNetCorePackContext.DependencyManager.ServiceCollection.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
            options.SuppressMapClientErrors = false;
        });

        aspNetCorePackContext.DependencyManager.ServiceCollection.AddOptions<MvcOptions>()
         .Configure<IServiceProvider>((options, serviceProvider) =>
         {
             options.Filters.Add<UnifyExceptionFilter>();
             options.Filters.Add<UnifyResultFilter>();
             options.Filters.Add<UnifyValidationFilter>();
             options.Filters.Add<UnifyActionFilter>();
         });

        return aspNetCorePackContext;
    }

}
